const child_process = require('child_process')

/**
 * ==== [tailwind-cli-for-uniapp] ====
 *
 * 针对 uniapp 配合 tailwindcss cli 模式，自动处理tailwindcss启动服务和打包的vite插件
 * 本插件只处理tailwindcss的扫描、编译、打包，原则上vite插件顺序应该第一个引入本插件
 * 
 * 既可以当作 vite 的 plugin 使用，也可以直接使用
 * 
 * 例子：
 * 
 *  [vite vue3]
 *  export default defineConfig({
        plugins: [
            tailwindCliRunner({
                command: process.env.NODE_ENV === 'production' ? 'npm run tailwind:build' : 'npm run tailwind:dev',
                async: process.env.NODE_ENV === 'production',
            }),
            uni(),
        ],
    })

    [webpack vue2]
    TailwindCssPlugin({
        command: process.env.NODE_ENV === 'production' ? 'npm run tailwind:build' : 'npm run tailwind:dev',
        async: process.env.NODE_ENV === 'production',
    })
    module.exports = {
        ......
    }
 *
 * 依赖: tailwindcss
 *
 * 1. 安装依赖 （然后参考 https://tailwindcss.com/docs/installation 创建配置文件，创建css文件并确保在App.vue或者main.js中引入该css文件）
 * npm install tailwindcss -D
 *
 * 2. 配置命令
 * 把如下两条命令配置到package.json的scripts部分
 * "tailwind:dev": "tailwindcss -i ./tailwind-input.css -o ./static/tailwind.css --watch",
 * "tailwind:build": "tailwindcss -i ./tailwind-input.css -o ./static/tailwind.css -m",
 *
 * 3. 在vue.config.js中引入本文件导出的函数，并执行
 *
 * 4. 在main.js中引入 /static/tailwind.css 文件 （不建议在App.vue中引入，开发时会存在缓存问题）
 *
 * 原理:
 * 相当于在vite启动之前，先通过命令行执行 npx tailwindcss --watch 指令，让tailwindcss启动监听服务或打包，生成一个目标css文件。然后工程将引入该css文件，实现tailwindcss的使用。
 * 由于tailwindcss的开发监听模式是命令行持久型（不立刻触发结束），所以本指令可能是同步可能是异步，配置中相关项就是对这种情况的处理
 */

const pluginName = 'tailwind-cli-runner'
const defaultOption = {
    /** tailwind 启动指令 */
    command: 'npm run tailwind:dev',
    /** 启动指令是否是同步的 */
    async: false,
    /** 如果是异步指令，指令首次收到消息后触发回调的延迟时间 ms */
    syncDely: 800,
}

function tailwindCliRunner(inputOption = defaultOption) {
    console.log(`[${pluginName}] start running`)

    const options = Object.assign({}, defaultOption, inputOption)

    return new Promise((resolve, reject) => {
        const child = child_process.exec(
            options.command,
            {
                cwd: __dirname, // 切换目录到当前项目，必须
            },
            (error, stdout, stderr) => {
                // tailwind --watch 是一个持久进程，不会立即执行回调
                // process.stdout.write('tailwind success')
                if (error) {
                    console.error(`[${pluginName}] exec command error, plase check`)
                    reject(error)
                }

                if (options.async) {
                    resolve()
                }
            }
        )
        child.stdout.on('data', (data) => {
            process.stdout.write(data)
            if (!options.async) {
                setTimeout(() => resolve(), options.syncDely)
            }
        })
    })
}

module.exports = tailwindCliRunner
